package me.zhengjie.modules.fund.service.impl;

import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.fund.domain.Fund;
import me.zhengjie.modules.fund.domain.UserFundFlow;
import me.zhengjie.modules.fund.repository.UserFundFlowRepository;
import me.zhengjie.modules.fund.service.FundService;
import me.zhengjie.modules.fund.service.UserFundFlowService;
import me.zhengjie.modules.fund.service.dto.UserFundFlowDto;
import me.zhengjie.modules.fund.service.dto.UserFundFlowQueryCriteria;
import me.zhengjie.modules.fund.service.mapstruct.UserFundFlowMapper;
import me.zhengjie.utils.ElAdminConstant;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

@Slf4j
@Service
public class UserFundFlowServiceImpl implements UserFundFlowService {

    @Resource
    private UserFundFlowRepository userFundFlowRepository;

    @Resource
    private UserFundFlowMapper userFundFlowMapper;

    @Resource
    private FundService fundService;

    /**
     * @param resources
     * @see UserFundFlowService#create(UserFundFlow)
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(UserFundFlow resources) {
        Fund fund = fundService.findByCode(resources.getFundCode());
        if (Objects.isNull(fund)) {
            throw new BadRequestException("基金编码：" + resources.getFundCode() + " 不存在");
        }
        resources.setFundName(fund.getName());

        if (Objects.isNull(resources.getConfirmNetValue())) {
            resources.setStatus(ElAdminConstant.UserFundFlowStatus.OnOrder);
        } else {
            resources.setStatus(ElAdminConstant.UserFundFlowStatus.Confirmed);
        }

        userFundFlowRepository.save(resources);
    }

    /**
     * @param resources
     * @see UserFundFlowService#update(UserFundFlow)
     */
    @Override
    public void update(UserFundFlow resources) {
        UserFundFlow userFundFlow = userFundFlowRepository.findById(resources.getId()).orElseGet(UserFundFlow::new);
        ValidationUtil.isNull(userFundFlow.getId(), "UserFundFlow", "id", resources.getId());
        resources.setId(userFundFlow.getId());

        Fund fund = fundService.findByCode(resources.getFundCode());
        if (Objects.isNull(fund)) {
            throw new BadRequestException("基金编码：" + resources.getFundCode() + "不存在");
        }
        resources.setFundName(fund.getName());

        if (Objects.isNull(resources.getConfirmNetValue())) {
            resources.setStatus(ElAdminConstant.UserFundFlowStatus.OnOrder);
        } else {
            resources.setStatus(ElAdminConstant.UserFundFlowStatus.Confirmed);
        }

        userFundFlowRepository.save(resources);
    }

    /**
     * @param ids 要删除的ids
     * @see UserFundFlowService#delete(Set)
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Set<Long> ids) {
        userFundFlowRepository.deleteAllByIdIn(ids);
    }

    /**
     * @param criteria 查询条件
     * @param pageable
     * @return
     * @see UserFundFlowService#queryAll(UserFundFlowQueryCriteria, Pageable)
     */
    @Override
    public Page<UserFundFlowDto> queryAll(UserFundFlowQueryCriteria criteria, Pageable pageable) {
        Page<UserFundFlow> pageUserFundFlows = userFundFlowRepository.findAll((root, queryCriteria, queryBuilder) -> QueryHelp.getPredicate(root, criteria, queryBuilder), pageable);

        List<UserFundFlowDto> userFundFlowDtos = userFundFlowMapper.toDto(pageUserFundFlows.getContent());

        BigDecimal totalAmount = BigDecimal.ZERO;
        for (UserFundFlowDto userFundFlow : userFundFlowDtos) {
            totalAmount = totalAmount.add(userFundFlow.getOperateAmount());
        }

        List<UserFundFlowDto> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(userFundFlowDtos)) {
            UserFundFlowDto totalFundFlow = new UserFundFlowDto();
            totalFundFlow.setFundName("合计");
            totalFundFlow.setOperateAmount(totalAmount);

            result.add(totalFundFlow);
        }
        result.addAll(userFundFlowDtos);

        return new PageImpl<>(result, pageable, pageUserFundFlows.getTotalElements());
    }

    /**
     * @param criteria
     * @return
     * @see UserFundFlowService#queryAll(UserFundFlowQueryCriteria)
     */
    @Override
    public List<UserFundFlowDto> queryAll(UserFundFlowQueryCriteria criteria) {
        List<UserFundFlow> userFundFlows = userFundFlowRepository.findAll((root, queryCriteria, queryBuilder) -> QueryHelp.getPredicate(root, criteria, queryBuilder));
        return userFundFlowMapper.toDto(userFundFlows);
    }
}
